美团外卖开发总结

准备工作

首先需要申请开发者账号,地址:http://developer.meituan.com/home。通过之后可以得到developerId:10**16和SignKey:s9bvk***mjm9xms以及测试门店信息。

开发者可使用美团外卖app端,修改定位到: 墨脱县–搜索色金拉–搜索测试门店名称测试下单。门店管理可以使用美团外卖商家版APP进行管理。

对接可以使用美团开发平台SDK或者UISDK。开发平台SDK下载地址:

https://drive.google.com/open?id=14RkrayTt_MKb2d38FhN8aHop-shEv9nJ

绑定与解绑

美团外卖商家绑定地址为:https://open-erp.meituan.com/login?developerId=101416&businessId=2&ePoiId=123324214214&signKey=s9bvktibcmjm9xms

除了developerIdSignKey之外,还需传入businessId(2表示外卖业务)和ePoiId(该商户在ERP厂商上的唯一标识码)。

绑定成功后,美团会返回一个appAuthToken(绑定门店成功后开放平台生产的token)。在回调方法中(下面会说到)将该token保存到数据库,用于后续调用接口。

美团外卖商家解绑地址为:https://open-erp.meituan.com/releasebinding?signKey=s9bvktibcmjm9xms&businessId=2&appAuthToken=35be4d3e63270abd28b9a320611bbdb616b1bd6ac7e11fce132e11196a4e6c89558b10f5d651d355a135bf7c49da75c2

其中appAuthToken为门店绑定的时候生成的token。

回调

美团开发平台为外卖各个流程状态提供了回调URL,如下图所示: 1252b9de2d36b7b79430975b37a61f27.png

回调URL对应为项目中方法的请求地址,比如订单推送URL对应项目中的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 美团外卖订单推送回调
* @param order
* @return
*/
@ResponseBody
@RequestMapping(value="/plugpay/mtOrderPush.php",produces={"application/json;charset=UTF-8"})
public Map<String,String> mtOrderPush(String order){
synchronized (this) {
Map<String, String> result = new HashMap<String, String>();
System.out.println(order);
System.out.println("您有新的美团外卖订单,请及时处理");
// 保存订单到数据库...
result.put("data", "OK");
return result;
}
}

订单推送回调方法需要返回{"data": "OK"}JSON数据,代表推送成功,否则开发平台会间隔时间连续推送。

其中关于回调返回的字段可参考美团开发平台回调API:http://developer.meituan.com/openapi#7.5.1

除了订单回调,美团开发平台还提供了门店绑定和解绑的回调,和订单类似,配置好回调URL即可。比如门店绑定回调方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 门店绑定成功回调
* @param appAuthToken
* @param businessId
* @param ePoiId
* @param timestamp
* @return
*/
@ResponseBody
@RequestMapping(value="/plugpay/mtOauth.php",produces={"application/json;charset=UTF-8"})
public JSONObject saveLogin(String appAuthToken, String businessId, String ePoiId, String timestamp){
synchronized (this) {
JSONObject jsonObject = new JSONObject();
System.out.println("appAuthToken: "+appAuthToken+"businessId: "+businessId+"ePoiId: "+ePoiId+
"timestamp: "+timestamp);
System.out.println("商户绑定成功");
// 保存token...
jsonObject.element("data","success");
return jsonObject;
}
}

除此之外,还有一个比较特殊的回调:

e5599ac7f483c99789ed90606921bffa.png

心跳是用来检测餐饮商户设备是否正常工作的定时机制,其中餐饮商户的设备包括所使用的ERP系统的云端、pos等各类设备。心跳由ERP厂商负责上报,聚宝盆开放平台负责收集,并将收集到的结果应用于外卖、点餐等业务线。

回调方法很简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 心跳
* @param request
* @return
*/
@ResponseBody
@RequestMapping(value="/plugpay/heartbeat.php",method={RequestMethod.GET})
public Map<String,String> mtHeartbeatBack(HttpServletRequest request){
Map<String, String> result = new HashMap<String, String>();
result.put("data", "OK");
System.out.println("mtHeartbeat "+System.currentTimeMillis());
return result;
}

使用SDK操作订单

SDK中各个API对应的封装类按如下规则命名:通用前缀 + 业务类型前缀 + 业务二级前缀 + 具体操作 + 通用后缀。

比如确认外卖订单请求的URL为:http://api.open.cater.meituan.com/waimai/order/confirm

接口对应完整类为:CipCater + Takeout + Order + Confirm + Request = CipCaterTakeoutOrderConfirmRequest。

返回结果为JSON字符串。

具体例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
JSONObject result_json = new JSONObject();
// 声明公共参数,RequestSysParams构造方法接收两个参数,第一个为signkey,第二个为appAuthToken
RequestSysParams requestSysParams = new RequestSysParams("yourSecret", "yourToken");
// 声明所需request,此Request对象为根据url在表中查询获得
CipCaterTakeoutOrderConfirmRequest request = new CipCaterTakeoutOrderConfirmRequest();
// 设置公共参数
request.setRequestSysParams(requestSysParams);
// 设置业务级参数
request.setOrderId(orderId);
// 准备接收返回Json
String resultJson = "";
try {
// 发送请求,接收Json,所有Request都有doRequest方法直接调用即可
result_json = JSONObject.fromObject(request.doRequest());
} catch (IOException e) {
// 处理io异常
} catch (URISyntaxException e) {
// 处理URI语法异常
}
String data = getJsonValueString(result_json, "data");
if("OK".equalsIgnoreCase(data)){
// 成功
}else{
JSONObject error = JSONObject.fromObject(getJsonValueString(result_json, "error"));
String message = getJsonValueString(error, "message");
//失败
}

其中getJsonValueString方法作用为根据字段名从JSON中获取值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 根据名称获取Json里的值
* @param json
* @param name
* @return
*/
public String getJsonValueString(JSONObject json,String name) {
return json.has(name)?json.getString(name):"";
}
public int getJsonValueInt(JSONObject json,String name) {
return json.has(name)?json.getInt(name):0;
}
public double getJsonValueDouble(JSONObject json,String name) {
return json.has(name)?json.getDouble(name):0.0;
}
public boolean getJsonValueBoolean(JSONObject json,String name) {
return json.has(name)?json.getBoolean(name):false;
}
public JSONArray getJsonValueArray(JSONObject json,String name) {
return json.has(name)?json.getJSONArray(name):new JSONArray();
}
public JSONObject getJsonValueObj(JSONObject json,String name) {
return json.has(name)?json.getJSONObject(name):new JSONObject();
}

使用的JSON包为net.sf.json

其他接口的使用以此类推。

请作者喝瓶肥宅水🥤

0